package net

import (
	"context"
	"fmt"
	"net"
	"sync"

	"github.com/gogf/gf/v2/os/glog"
	"google.golang.org/grpc"
)

var (
	grpcServer *grpc.Server
	services   []*service
	ctx        = context.Background()
	once       = &sync.Once{}
)

// ## service

func RegisterService(srv ServiceDesc) {
	services = append(services, &service{
		sd: srv.GrpcGetServiceDesc(),
		ss: srv,
	})
}

type service struct {
	sd *grpc.ServiceDesc
	ss interface{}
}

// # backend

func Server(address string) *server {
	return &server{
		address: address,
	}
}

type server struct {
	address string
}

func (s *server) Run() {
	once.Do(func() {
		listen, err := net.Listen("tcp", s.address)
		if err != nil {
			panic(err)
		}

		grpcServer = grpc.NewServer()
		for _, s := range services {
			grpcServer.RegisterService(s.sd, s.ss)
		}

		glog.New().Info(ctx, fmt.Sprintf("gprc backend started listening on %v", listen.Addr()))
		if err := grpcServer.Serve(listen); err != nil {
			glog.New().Fatal(ctx, "failed to serve grpc backend", err)
		}
	})
}
